<?php

namespace IDock\Insurance\ZSIC\Request;

use Exception;
use IDock\Insurance\ZSIC\Response\PremiumInquiryResponse;
use IDock\Insurance\ZSIC\ZSICEnums;
use IDock\Visitor\NonCar\NonCarProductVisitor;
use IDock\Visitor\Premium\PremiumChargingPileVisitor;
use IDock\Visitor\Premium\PremiumCoverageVisitor;
use IDock\Visitor\Premium\PremiumDeviceVisitor;
use IDock\Visitor\Premium\PremiumInquiryVisitor;
use IDock\Visitor\Premium\PremiumRelationVisitor;

class PremiumInquiryRequest extends AllZSICRequest
{

    public $requestCode = 'calculate';

    protected $response = PremiumInquiryResponse::class;

    protected $urlTip = '报价接口';

    /*** @var  PremiumInquiryVisitor $visitor */
    protected $visitor;

    /**
     * @throws Exception
     */
    public function generate(): array
    {
        $this->channelCode = $this->visitor->extInfoVisitor->argc['channelCode'] ?? '';
        $this->cityCode = $this->visitor->extInfoVisitor->argc['cityCode'] ?? '';

        $quoteType = 2;
        if (!empty($this->visitor->biStartData) && empty($this->visitor->ciStartData)) {
            $quoteType = 0;
        }
        if (empty($this->visitor->biStartData) && !empty($this->visitor->ciStartData)) {
            $quoteType = 1;
        }
        $data = [
            'base' => [
                'quoteType' => $quoteType,//投保类型
                'vciProductVersion' => $this->visitor->getBiStartData() ? ($this->visitor->isNewEnergy ? 'NE' : '20') : '',//商业险险种版本
                'vciEffectiveDate' => $this->visitor->getBiStartData(),//商业险-保险起期
                'tciEffectiveDate' => $this->visitor->getCiStartData(),//交强险-保险起期
                'vciExpiryDate' => $this->visitor->getBiEndData(),
                'tciExpiryDate' => $this->visitor->getCiEndData(),
//                'modifiedActualValue' => '0',//协商价
                'tciEffectImmediatly' => intval(boolval($this->visitor->biEffectFlag)),
                'vciEffectImmediatly' => intval(boolval($this->visitor->ciEffectFlag)),
//                'vciDiscount' => $this->visitor->getExtInfoVisitor()->expectedDiscount,//期望折扣
                'quotationNo' => $this->visitor->getExtInfoVisitor()->argc['quotationNo'] ?? '',//上次询价单号
                'disputeResolution' => '',//争议解决方式
                'disputeOrg' => '',//仲裁机构
                'serialPolicy' => '0',//是否多年联单
//                'agreementCode' => '',//协议代码
//                'agreementName' => '',//协议名称
//                'insuranceAgentId' => '',//保司代理人证件号
//                'insuranceAgentName' => '',//保司代理人姓名
            ],
            'coverages' => $this->getCoverageList(),
            'vehicle' => $this->getVehicle(),
            'parties' => $this->getRelation(),
            'vehicleInspection' => $this->getVehicleInspection()
        ];
        if (isset($this->visitor->getExtInfoVisitor()->argc['businessNo'])) {
            $data['base']['pricingRate'] = $this->visitor->getExtInfoVisitor()->selfPricingFactor;//自主定价系数
        }
        $data['tax'] = $this->carShipTaxBi();
        if (!empty($this->visitor->ciStartData)) {
            $data['tax'] = $this->carShipTax();
        }
        if (!empty($this->visitor->getNonCarInquiryVisitor()->getNonCarList())) {
            $data['nonVehicleProducts'] = $this->getNonCarList();
        }
        if (!empty($this->visitor->getChargingPileVisitorList())) {
            $data['chargingPostDatas'] = [];
            foreach ($this->visitor->getChargingPileVisitorList() as $value) {
                /** @var PremiumChargingPileVisitor $value */
                $item = [
                    'chargingPostType' => $value->chargingPileType,
                    'chargingPostCode' => $value->chargingPileCode,
                    'chargingPostAddress' => $value->chargingPileAddress,
                    'chargingPostAddressType' => ZSICEnums::$chargingPileAddressType[$value->chargingPileAddressType] ?? '',
                    'chargingPostKind' => ZSICEnums::$chargingPileKind[$value->chargingPileKind] ?? '',
                    'chargingPostYearLimit' => ZSICEnums::$chargingPileYearLimit[$value->chargingPileYearLimit] ?? '',
                ];
                if (!empty($value->lossAmount)) {
                    $item['cdzdAmount'] = $value->lossAmount;
                } else {
                    $item['cdzrAmount'] = $value->liabilityAmount;
                }
                $data['chargingPostDatas'][] = $item;
                unset($item);
            }
        }

        if ($this->visitor->getDeviceList()) {
            $data['deviceDomains'] = $this->getDeviceList();
        }

        return $data;
    }

    public function getNonCarList(): array
    {
        $item = [];
        /*** @var NonCarProductVisitor $single */
        $single = $this->visitor->getNonCarInquiryVisitor()->getNonCarList()[0] ?? [];
        $item['productCode'] = $single->productCode;
        $item['planCode'] = $single->planCode;
        $item['effectiveDate'] = date('Y-m-d', strtotime($this->visitor->biStartData ?: $this->visitor->ciStartData));
        $item['expiryDate'] = date('Y-m-d', strtotime($this->visitor->biEndData ?: $this->visitor->ciEndData));
        $item['purchaseNumber'] = $single->insuredNum;
        $item['unitPremium'] = $single->premium;
        return ['nonVehicleProduct' => $item];
    }

    public function getVehicleInspection(): array
    {
        return [
            'checkStatus' => ZSICEnums::$carCheckCode[$this->visitor->getExtInfoVisitor()->carCheckCode] ?? '',
            'checkReason' => ZSICEnums::$carCheckReasonKind[$this->visitor->getExtInfoVisitor()->carCheckReasonKind] ?? '',
            'checkPerson' => $this->visitor->getExtInfoVisitor()->carChecker,
            'checkDate' => $this->visitor->getExtInfoVisitor()->carCheckDate,
            'description' => '',
        ];
    }

    /**
     * @throws Exception
     */
    public function getCoverageList(): array
    {
        $list = [];
        $coverageList = $this->visitor->getCoverageVisitorList();
        /*** @var PremiumCoverageVisitor $item */
        foreach ($coverageList as $item) {
            $tmp = [
                'productCode' => $item->coverageCode == 'C01001' ? 'MAUTO' : 'GAUTO',
                'coverageCode' => $item->coverageCode == 'C01001' ? 'COMPAUTO' : (ZSICEnums::$coverageCode[$item->coverageCode] ?? ''),
                'limitAmount' => $item->amount,
            ];
            if ($tmp['productCode'] == 'MAUTO') {
                $tmp['limitAmount'] = '200000';
            }

            //车损险保额
            if ($tmp['productCode'] == 'AOD') {
                $tmp['limitAmount'] = $this->visitor->vehicleVisitor->negotiatedValue?:$this->visitor->vehicleVisitor->actualValue;
            }

            if ($item->coverageCode == 'C02004' or $item->coverageCode == 'C12004') {
                throw new Exception("不支持附加车轮单独损失险");
            }
            if (in_array(ZSICEnums::$coverageCode[$item->coverageCode], ['AD_MP_AOD', 'AD_MP_ATP', 'AD_MP_ADL', 'AD_MP_APL'])) {
                //绝对免赔率
                $tmp['rate'] = round($item->deductionRate / 100, 2);
            }
            if (in_array(ZSICEnums::$coverageCode[$item->coverageCode], ['APL', 'AMD_APL', 'DODA_APL'])) {
                $tmp['unitAmount'] = $item->unitAmount ?: $item->amount;
                $tmp['count'] = $this->visitor->getVehicleVisitor()->vehicleSeat - 1;
                $tmp['seatNo'] = $this->visitor->getVehicleVisitor()->vehicleSeat - 1;
                $tmp['limitAmount'] = round($tmp['unitAmount'] * $tmp['count']);
            }
            if (in_array(ZSICEnums::$coverageCode[$item->coverageCode], ['DODA_ADL', 'ADL'])) {//DODA_ADL
                //司机险
                $tmp['count'] = 1;
                $tmp['seatNo'] = 1;
                $tmp['unitAmount'] = $item->amount;
            }
            if (in_array(ZSICEnums::$coverageCode[$item->coverageCode], ['AD_MP_JY', 'AD_MP_JC', 'AD_MP_DJ', 'AD_MP_SJ'])) {
                //道路救援等
                $tmp['count'] = $item->serviceTimes;
            }

            if (ZSICEnums::$coverageCode[$item->coverageCode] == 'CDR') {
                $tmp['count'] = $item->quantity;
                $tmp['unitAmount'] = $item->amount;
                $tmp['limitAmount'] = intval($item->quantity) * $item->amount;
            }
            $list[] = $tmp;
            unset($tmp);
        }
        return ['coverage' => $list];
    }

    public function carShipTax(): array
    {
        $arr = [
            'fuelType' => ZSICEnums::$energyType[$this->visitor->getVehicleVisitor()->energyTypeCode] ?? '',
            'taxpayerName' => $this->visitor->getApplicantVisitor()->name,
            'idType' => ZSICEnums::$certificateTypeCode[$this->visitor->getApplicantVisitor()->certificateTypeCode] ?? '',
            'idNumber' => $this->visitor->getApplicantVisitor()->certificateNo,
            'taxStatus' => ZSICEnums::$taxTypeCode[$this->visitor->getCarTaxVisitor()->taxTypeCode] ?? '',
            'relifReason' => ZSICEnums::$taxReductionReasonCode[$this->visitor->getCarTaxVisitor()->taxReductionReasonCode] ?? '',//减免税原因
            'paidFreeCertificate' => $this->visitor->getCarTaxVisitor()->taxpayerCertificateNo,
        ];
        if ($this->visitor->getCarTaxVisitor()->taxTypeCode == 'T02') {
            $arr['taxDocumentDate'] = $this->visitor->getCarTaxVisitor()->taxDocumentDate;
            $arr['taxPaidAreaCode'] = $this->visitor->getCarTaxVisitor()->taxPaidAreaCode;
        } else {
            //减税
            $arr['deductionType'] = $this->visitor->getCarTaxVisitor()->taxReductionCode;
            if ($arr['deductionType'] == 'P') {
                $arr['deductionProportion'] = $this->visitor->getCarTaxVisitor()->taxFreeRate;
            } else {
                $arr['deductionAmount'] = $this->visitor->getCarTaxVisitor()->taxExemption;
            }

        }
        return $arr;
    }

    public function carShipTaxBi(): array
    {
        return [
            'fuelType' => ZSICEnums::$energyType[$this->visitor->getVehicleVisitor()->energyTypeCode] ?? '',
            'idNumber' => $this->visitor->getApplicantVisitor()->certificateNo,
            'idType' => ZSICEnums::$certificateTypeCode[$this->visitor->getApplicantVisitor()->certificateTypeCode] ?? '',
            'taxpayerName' => $this->visitor->getApplicantVisitor()->name,
        ];
    }

    public function getVehicle(): array
    {
        return [
            "licenseFlag" => intval(boolval($this->visitor->getVehicleVisitor()->licenseNo)),
            "licenseNo" => $this->visitor->getVehicleVisitor()->licenseNo,
            "ownerName" => $this->visitor->getOwnerVisitor()->name,
            "idType" => ZSICEnums::$certificateTypeCode[$this->visitor->getOwnerVisitor()->certificateTypeCode] ?? '',
            "idNumber" => $this->visitor->getOwnerVisitor()->certificateNo,
            "engineNo" => $this->visitor->getVehicleVisitor()->engineNo,
            "frameNo" => $this->visitor->getVehicleVisitor()->vin,
            "printBrandName" => $this->visitor->getVehicleVisitor()->vehicleModel,
            "firstRegistrationDate" => $this->visitor->getVehicleVisitor()->firstRegisterDate,
            "modelCode" => $this->visitor->getVehicleVisitor()->vehicleModelCode,
            "platformModelCode" => $this->visitor->getVehicleVisitor()->argc['platformModelCode'] ?? '',
            "noticeType" => '',
            "purchasePrice" => $this->visitor->getVehicleVisitor()->vehiclePrice,
            "seat" => $this->visitor->getVehicleVisitor()->vehicleSeat,
            "capacity" => round(round($this->visitor->getVehicleVisitor()->vehicleExhaust, 3) * 1000, 2),
            "importFlag" => ZSICEnums::$importFlag[$this->visitor->getVehicleVisitor()->vehicleImport] ?? '',
            "weight" => floatval($this->visitor->getVehicleVisitor()->wholeWeight),
            'tonnage' => floatval($this->visitor->getVehicleVisitor()->vehicleTonnage),
            'transferFlag' => intval($this->visitor->getVehicleVisitor()->isTransfer),
            'cTfiSpecialMrk' => intval($this->visitor->getVehicleVisitor()->isCiTransfer),
            'transferDate' => $this->visitor->getVehicleVisitor()->transferDate,
            'issueDate' => $this->visitor->getVehicleVisitor()->issueDate,
            'vehicleType' => $this->getVehicleType(),
            'businessType' => ZSICEnums::$useNatureCode[$this->visitor->getVehicleVisitor()->useNatureCode] ?? '',
            'pmOriCode' => $this->visitor->getVehicleVisitor()->vehicleStyleCode,
            'licenseColor' => ZSICEnums::$licenseColorCode[$this->visitor->getVehicleVisitor()->licenseColorCode] ?? '',
            'ownershipType' => ZSICEnums::$attachNature[$this->visitor->getVehicleVisitor()->attachNature] ?? '',
            'purchaseDate' => '',//purchaseDate
            'useType' => ZSICEnums::$causeType[$this->visitor->getVehicleVisitor()->causeType] ?? '',
            'drivingArea' => '',
            'vehicleCategory' => ZSICEnums::$carKindCode[$this->visitor->getVehicleVisitor()->carKindCode] ?? '',
            'loanFlag' => '0',
            "customerType" => $this->visitor->getOwnerVisitor()->typeCode == 'R1' ? '1' : '2',
            "vehicleCertiType" => $this->visitor->vehicleVisitor->carCertificateType,
            "vehicleCertiNo" => $this->visitor->vehicleVisitor->carCertificateNo,
            "vehicleCertiDate" => $this->visitor->vehicleVisitor->carCertificateDate? date('Ymd',strtotime($this->visitor->vehicleVisitor->carCertificateDate)) : '',
            "vehicleClassCode" => '',
            "licenseType" => ZSICEnums::$licenseTypeCode[$this->visitor->getVehicleVisitor()->licenseTypeCode] ?? '',
            "mortgageOrg" => '',
            "mortgagePeriod" => '',
            "mortgagePhase" => '',
            "lastYearProposalNo" => '',
            "fuelType" => ZSICEnums::$energyType[$this->visitor->getVehicleVisitor()->energyTypeCode] ?? '',
            "fuelTypeOtherDesc" => '',
            "mortgageClaimRequirement" => '',
            "actualValue" => '',
            "power" => $this->visitor->getVehicleVisitor()->power,
            "brandId" => '',
            "modelName" => $this->visitor->getVehicleVisitor()->vehicleModel,
            "brand" => $this->visitor->getVehicleVisitor()->argc['brand'] ?? '',
            "dealerType" => '',
            "dealerName" => '',
            "dealerCityCode" => '',
            "localCarFlag" => '',
            "absFlag" => '',
            //"carColor" => ZSICEnums::$vehicleColor[$this->visitor->getVehicleVisitor()->vehicleColor] ?? '',
            'color' => ($this->visitor->vehicleVisitor->argc['color'] ?? '') ? $this->visitor->vehicleVisitor->argc['color'] : '999'
        ];
    }

    /**
     * @throws Exception
     */
    public function getRelation(): array
    {
        $owner = $this->buildRelation($this->visitor->getOwnerVisitor());
        $owner['insuredFlag'] = '3';
        $apply = $this->buildRelation($this->visitor->getApplicantVisitor());
        $apply['insuredFlag'] = '2';
        $insured = $this->buildRelation($this->visitor->getInsuredVisitor());
        if ($insured['name'] != $owner['name']) {
            $insured['relationShip'] = 9;
        }
        $insured['insuredFlag'] = '1';
        return ['party' => array_values([$owner, $apply, $insured])];

    }

    /**
     * 通过身份证获取性别
     * @param $idCard
     * @return string
     * @throws
     */
    private function getGenderByIdCard($idCard): string
    {
        if (strlen($idCard) != 18) {
            throw new Exception("身份证位数不合法");
        }
        $gender = intval(substr($idCard, 16, 1)) % 2;
        return $gender ? '1' : '2';
    }

    /**
     * 通过身份证获取生日
     * @param $idCard
     * @return string
     * @throws
     */
    private function getBirthday($idCard): string
    {
        if (strlen($idCard) != 18) {
            throw new Exception("身份证位数不合法");
        }
        return substr($idCard, 6, 4) . '-' . substr($idCard, 10, 2) . '-' . substr($idCard, 12, 2);
    }

    /**
     * @throws Exception
     */
    public function buildRelation($model): array
    {
        /**@var PremiumRelationVisitor $model */
        $arr = [
            'insuredFlag' => '',
            'customerType' => $model->typeCode == 'R1' ? '1' : '2',
            'name' => $model->name,
            'sex' => $this->getGenderByIdCard($model->certificateNo),
            'birthday' => $this->getBirthday($model->certificateNo),
            'idType' => ZSICEnums::$certificateTypeCode[$model->certificateTypeCode] ?? '',
            'idNumber' => $model->certificateNo,
            'telephone' => '',
            'mobile' => $model->mobile,
            'provinceCode' => $model->provinceCode,
            'provinceName' => $model->provinceName,
            'cityCode' => $model->cityCode,
            'cityName' => $model->cityName,
            'areaCode' => $model->areaCode,
            'areaName' => $model->areaName,
            'address' => $model->address,
            'eMail' => $model->email,
            'postCode' => $model->postcode,
            'taxType' => '',//纳税人类型 01 一般纳税人 02 小规模纳税人
            'billBankName' => '',
            'billBankAccount' => '',
            'billRequire' => '',
            'taxIdentificationNo' => '',
            'permanentId' => $model->certificateEndDate == '2099-12-31' ? '1' : '0',
            'idStartDate' => $model->certificateStartDate,
            'idExpireDate' => $model->certificateEndDate,
            'nationality' => 'CHN',
            'occupation' => '',
            'businessScop' => '',
            'contactPerson' => $model->linkManName,
            'contactPersonIdType' => ZSICEnums::$certificateTypeCode[$model->linkManCertificateTypeCode] ?? '',
            'contactPersonIdNumber' => $model->linkManCertificateNo,
            'relationShip' => $model->typeCode == 'R1' ? '1' : '2',//与车辆关系 1 车辆所有人  2 车辆管理人
            'phoneOwnerName' => $model->name,
            'phoneOwnerIdType' => ZSICEnums::$certificateTypeCode[$model->certificateTypeCode] ?? '',
            'phoneOwnerIdNumber' => $model->certificateNo,
            'payAccountName' => '',
            'payRelationshipCode' => '',
            'payRelationshipComment' => '',
            'organizationType' => '',
            'industry' => '',
            'isIndividualBusiness' => '',
        ];
        if ($arr['customerType'] == '2') {
            $arr['taxType'] = '01';
        }
        return $arr;
    }

    public function getVehicleType(): string
    {
        $model = new VehicleActualValueRequest();
        return $model->getVehicleType($this->visitor->vehicleVisitor->carKindCode,$this->visitor->vehicleVisitor->vehicleSeat,$this->visitor->vehicleVisitor->vehicleTonnage);
    }

    public function address(): array
    {
        return [
            'province' => $this->visitor->getOwnerVisitor()->provinceCode,
            'city' => $this->visitor->getOwnerVisitor()->cityCode,
            'district' => $this->visitor->getOwnerVisitor()->areaCode,
            'accountUser' => '',
            'netPointCode' => '',
        ];
    }

    /**
     * 意外险
     * @return array
     */
    private function accident(): array
    {
        $list = [];
        if (!$this->visitor->getNonCarInquiryVisitor()->getNonCarList()) {
            return $list;
        }
        /*** @var NonCarProductVisitor $NonCarProductVisitor */
        foreach ($this->visitor->getNonCarInquiryVisitor()->getNonCarList() as $NonCarProductVisitor) {
            $list[] = [
                'rideRiskCode' => $NonCarProductVisitor->planCode,
                'quantity' => $NonCarProductVisitor->insuredNum,
            ];
        }

        return $list;
    }

    /**
     * 新增设备
     * @return array
     */
    private function getDeviceList(): array
    {
        $deviceList = [];
        /*** @var PremiumDeviceVisitor $device */
        foreach ($this->visitor->getDeviceList() as $device) {
            $deviceList[] = [
                'deviceName' => $device->deviceName,
                'quantity' => $device->quantity,
                'buyDate' => $device->buyDate,
                'purchasePrice' => $device->purchasePrice,
            ];
        }
        return $deviceList;
    }

    public function getBusinessNo()
    {
        return $this->visitor->getExtInfoVisitor()->argc['businessNo'] ?? '';
    }
}
